package com.ello.base.utils

import android.Manifest
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.database.Cursor
import android.net.Uri
import android.os.Build
import android.provider.MediaStore
import androidx.activity.ComponentActivity
import androidx.activity.result.PickVisualMediaRequest
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.lifecycleScope
import com.ello.base.ktx.lllog
import com.ello.base.ktx.register
import com.ello.base.ktx.toast
import com.permissionx.guolindev.PermissionX
import com.permissionx.guolindev.callback.RequestCallback
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

/**
 * @author dxl
 * @date   2023/6/9
 */

/**
 * 使用文件管理器选择文件
 * @param isMulti 是否多选
 * @param mimeTypes 限制类型
 * @param onResult 结果回调
 */
fun ComponentActivity.chooseFile(
    isMulti: Boolean = false,
    mimeTypes: Array<String> = arrayOf("*/*"),
    onResult: (List<Uri>) -> Unit
) {
    register(ActivityResultContracts.StartActivityForResult()) { activityResult ->
        val intent = activityResult.data
        if (activityResult.resultCode == AppCompatActivity.RESULT_OK && intent != null) {

            val uri = intent.data
            if (uri != null) {
                //只选择了一个
                onResult(listOf(uri))
                return@register
            }

            val clipData = intent.clipData
            if (clipData == null || clipData.itemCount <= 0) {
                onResult.invoke(emptyList())
                return@register
            }
            val selectedUris = mutableListOf<Uri>()
            for (i in 0 until clipData.itemCount) {
                selectedUris.add(clipData.getItemAt(i).uri)
            }
            onResult(selectedUris)

        } else {
            onResult.invoke(emptyList())
        }
    }.launch(
        Intent(Intent.ACTION_OPEN_DOCUMENT)
            .putExtra(Intent.EXTRA_MIME_TYPES, mimeTypes)
            .putExtra(Intent.EXTRA_ALLOW_MULTIPLE, isMulti)
            .setType("*/*")
    )
}


/**
 * 使用文件管理器选择媒体资源（照片或视频）
 * @param isMulti 是否多选
 * @param mediaType 仅图片、仅视频、图片和视频、自定义mimeType
 * @param onResult 结果回调
 */
fun ComponentActivity.chooseMediaByFile(
    isMulti: Boolean = false,
    mediaType: ActivityResultContracts.PickVisualMedia.VisualMediaType = ActivityResultContracts.PickVisualMedia.ImageAndVideo,
    onResult: (selectMedias: List<Uri>) -> Unit
) {
    val mimeTypes = when (mediaType) {
        is ActivityResultContracts.PickVisualMedia.ImageOnly -> arrayOf("image/*")
        is ActivityResultContracts.PickVisualMedia.VideoOnly -> arrayOf("video/*")
        is ActivityResultContracts.PickVisualMedia.ImageAndVideo -> arrayOf("image/*", "video/*")
        is ActivityResultContracts.PickVisualMedia.SingleMimeType -> arrayOf(mediaType.mimeType)
    }
    chooseFile(isMulti, mimeTypes, onResult)
}

/**
 * 使用手机相册选择照片或视频
 * @param isMulti 是否多选
 * @param isVideo true 选择视频 false 选择图片，不能同时选择
 * @param onResult 结果回调
 */
fun ComponentActivity.chooseMediaByAlbum(
    isMulti: Boolean = false,
    isVideo: Boolean = false,
    onResult: (List<Uri>) -> Unit
) {
    register(ActivityResultContracts.StartActivityForResult()) { activityResult ->

        if (activityResult.resultCode == AppCompatActivity.RESULT_OK && activityResult.data != null) {

            val uri = activityResult.data?.data
            if (uri != null) {
                //只选择了一个
                onResult(listOf(uri))
                return@register
            }

            val clipData = activityResult.data?.clipData
            if (clipData == null || clipData.itemCount <= 0) {
                onResult.invoke(emptyList())
                return@register
            }
            val selectedUris = mutableListOf<Uri>()
            for (i in 0 until clipData.itemCount) {
                selectedUris.add(clipData.getItemAt(i).uri)
            }
            onResult(selectedUris)
        } else {
            onResult.invoke(emptyList())
        }

    }.launch(Intent(Intent.ACTION_PICK).apply {
        type = if (isVideo) "video/*" else "image/*"
        putExtra(Intent.EXTRA_ALLOW_MULTIPLE, isMulti)
    })
}

/**
 * 使用相册选择照片
 * @param isMulti 是否多选
 * @param onResult 结果回调
 */
fun ComponentActivity.chooseImageByAlbum(
    isMulti: Boolean = false,
    onResult: (List<Uri>) -> Unit
) = chooseMediaByAlbum(isMulti, false, onResult)


/**
 * 使用相册选择视频
 * @param isMulti 是否多选
 * @param onResult 结果回调
 */
fun ComponentActivity.chooseVideoByAlbum(
    isMulti: Boolean = false,
    onResult: (List<Uri>) -> Unit
) = chooseMediaByAlbum(isMulti, true, onResult)

/**
 * 使用PickVisual选择媒体资源（照片或视频）
 * @param isMulti 是否多选
 * @param mediaType 仅图片、仅视频、图片和视频、自定义mimeType
 * @param onResult 结果回调
 */
fun ComponentActivity.chooseMediaByPickVisual(
    isMulti: Boolean = false,
    mediaType: ActivityResultContracts.PickVisualMedia.VisualMediaType = ActivityResultContracts.PickVisualMedia.ImageAndVideo,
    onResult: (List<Uri>) -> Unit
) {
    if (isMulti) {
        register(ActivityResultContracts.PickMultipleVisualMedia()) {
            onResult.invoke(it)
        }.launch(PickVisualMediaRequest(mediaType))
    } else {
        register(ActivityResultContracts.PickVisualMedia()) {
            if (it != null) {
                onResult(listOf(it))
            } else {
                onResult.invoke(emptyList())
            }
        }.launch(PickVisualMediaRequest(mediaType))
    }
}


object FileChooseUtil {

    sealed interface MediaType
    object Image : MediaType
    object Video : MediaType
    object ImageAndVideo : MediaType

    /**
     * 加载手机相册列表
     * 需要权限
     * @param activity
     * @param mediaType Image 图片  Video视频 ImageAndVideo 图片+视频
     */
    @SuppressLint("Range")
    fun loadAlbums(
        activity: FragmentActivity,
        mediaType: MediaType = ImageAndVideo,
        onProgress: (progress: Int) -> Unit,
        onResult: (List<AlbumFolder>) -> Unit
    ) {
        val permissions =
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                //安卓13以上系统
                listOf(
                    Manifest.permission.READ_MEDIA_IMAGES,
                    Manifest.permission.READ_MEDIA_VIDEO,
                    Manifest.permission.READ_MEDIA_AUDIO,
                )
            } else {
                listOf(
                    Manifest.permission.READ_EXTERNAL_STORAGE
                )
            }
        PermissionX.init(activity).permissions(permissions).explainReasonBeforeRequest()
            .request { allGranted, _, _ ->
                if (allGranted) {
                    val queryUri = when (mediaType) {
                        is Image -> MediaStore.Images.Media.EXTERNAL_CONTENT_URI
                        is Video -> MediaStore.Video.Media.EXTERNAL_CONTENT_URI
                        is ImageAndVideo -> MediaStore.Files.getContentUri("external")
                    }

                    activity.lifecycleScope.launch(Dispatchers.IO) {
                        val folders = mutableListOf<AlbumFolder>()
                        activity.contentResolver.query(
                            queryUri,
                            arrayOf(
                                MediaStore.Video.Media._ID,
                                MediaStore.Video.Media.BUCKET_ID,
                                MediaStore.Video.Media.BUCKET_DISPLAY_NAME,
                            ),
                            null,
                            null,
                            MediaStore.MediaColumns.DATE_MODIFIED + " DESC"
                        )?.use { cursor: Cursor ->
                            if (cursor.moveToFirst()) {
                                val firstUriId = cursor.getLong(cursor.getColumnIndex("_id"))
                                val totalNum = cursor.count
                                folders.add(
                                    AlbumFolder(
                                        AlbumFolder.ALL,
                                        folderName = "全部",
                                        firstUriId,
                                        totalNum
                                    )
                                )
                                var currentCount = 0
                                var currentProgress = 0
                                do {
                                    currentCount++
                                    val progress = currentCount * 100 / totalNum
                                    if (currentProgress != progress) {
                                        currentProgress = progress
                                        withContext(Dispatchers.Main) {
                                            onProgress.invoke(progress)
                                        }
                                    }
                                    val bucketId =
                                        cursor.getLong(cursor.getColumnIndex("bucket_id"))
                                    val bucketDisplayName =
                                        cursor.getString(cursor.getColumnIndex("bucket_display_name"))
                                    val id = cursor.getLong(cursor.getColumnIndex("_id"))

                                    val folder =
                                        folders.find { albumFolder -> albumFolder.bucketId == bucketId }
                                    if (folder == null) {
                                        folders.add(AlbumFolder(bucketId, bucketDisplayName, id, 1))
                                    } else {
                                        folder.totalNum++
                                    }
                                } while (cursor.moveToNext())
                            }
                        }
                        withContext(Dispatchers.Main) {
                            onResult.invoke(folders)
                        }
                    }


                } else {
                    "请到设置中开启读取文件权限".toast()
                }
            }
    }
}

/**
 * 相册
 */
data class AlbumFolder(
    val bucketId: Long = ALL,
    val folderName: String?,
    val firstImageUriId: Long,
    var totalNum: Int = 0
) {
    companion object {
        const val ALL = -1L
    }
}